﻿using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using UnityEditor;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

namespace IQIGame.Onigao.GamePlay
{
    public partial class StoryManager
    {
        private Dictionary<int, StoryNpc> _npcMap = new Dictionary<int, StoryNpc>();

#if UNITY_EDITOR
        public Dictionary<int, StoryNpc> npcMap => this._npcMap;
#endif
        
        private async UniTask PlayTimeline(string timeline)
        {
            var rTimelineAsset = await this.GetTimelineAsset(timeline);
            if (rTimelineAsset != null)
            {
                this._playable.playableAsset = rTimelineAsset;
                await this._playable.PlayAsync();
            }
        }
        
        private async UniTask<TimelineAsset> GetTimelineAsset(string name)
        {
            var rPath = PathConstant.GetStoryTimelinePath(name);
 
            TimelineAssetInfo rAsset = null;
#if UNITY_EDITOR
            if (StoryClientUtil.IsEditorMode)
            {
                rAsset = new TimelineAssetInfo()
                {
                    asset = UnityEditor.AssetDatabase.LoadAssetAtPath<TimelineAsset>("Assets/" + rPath),
                };
            }
            else
#endif
            {
                rAsset = await ManagerCenter.Timeline.Get(rPath);
            }
            var rAllTracks = new List<TrackAsset>(rAsset.asset.GetRootTracks());
            for (int i = 0; i < rAllTracks.Count; i++)
            {
                var rRootTrack = rAllTracks[i];
                if (rRootTrack == null) continue;
                if (rRootTrack is GroupTrack rGroup)
                {
                    var rTracks = rGroup.GetChildTracks();
                    var rTrackName = rGroup.name;
                    if (!int.TryParse(rTrackName, out var nStoryNpcID))
                    {
                        continue;
                    }
#if UNITY_EDITOR
                    if (StoryClientUtil.IsEditorMode)
                    {
                        if (TableCenter.storyNpc == null)
                        {
                            await TableCenter.LoadTables();
                        }
                    }
#endif

                    if (!this._npcMap.TryGetValue(nStoryNpcID, out var rNpc))
                    {
                        var rNpcConfig = TableCenter.storyNpc.Get(nStoryNpcID);
                        string rPrefabAssetPath;
                        if (rNpcConfig.EntityType == 1)
                        {
                            rPrefabAssetPath = PathConstant.GetCharacterBattlePrefabPath(rNpcConfig.EntityAsset);
                        }
                        else
                        {
                            rPrefabAssetPath = PathConstant.GetMonsterBattlePrefabPath(rNpcConfig.EntityAsset);
                        }
#if UNITY_EDITOR
                        if (StoryClientUtil.IsEditorMode)
                        {
                            var rPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/" + rPrefabAssetPath);
                            var rGo = BattleClientUtil.CreateGameobject(rPrefab, this._playable.transform);
                            rNpc = ClassPool<StoryNpc>.Get();
                            rNpc.gameObject = rGo;
                            rNpc.transform = rGo.transform;
                        }
                        else
#endif
                        {
                            var rEntity = ManagerCenter.Entity.Get(rPrefabAssetPath, (int)EntityPoolGroupType.StoryNpc) as StoryNpcEntity;
                            await rEntity.Load();
                            rNpc = ClassPool<StoryNpc>.Get();
                            rNpc.entity = rEntity;
                            rNpc.gameObject = rEntity.gameObject;
                            rNpc.transform = rEntity.transform;
                            rEntity.transform.SetParent(this._playable.transform);
                        }
                        this._npcMap[nStoryNpcID] = rNpc;
                    }
                    var rEntityDriver = rNpc.gameObject.GetComponent<EntityDriver>();
                    foreach (var rTrack in rTracks)
                    {
                        switch (rTrack)
                        {
                            case AnimationTrack rAnimeTrack:
                                var model = rNpc.transform.Find("model").gameObject;
                                var rAnimator = model.GetComponent<Animator>();
                                this._playable.SetGenericBinding(rAnimeTrack, rAnimator);
                                break;
                            case UnitEffectTrack:
                                if (this._playable.GetGenericBinding(rTrack) == null)
                                {
                                    this._playable.SetGenericBinding(rTrack, rEntityDriver);
                                }
                                var rRefValue = this._playable.GetReferenceValue(TimelineAssetInfo.RefInfoID, out var bIsValid);
                                if (!bIsValid || !(rRefValue is TimelineAssetInfoHandler rHandler))
                                {
                                    rHandler = ScriptableObject.CreateInstance<TimelineAssetInfoHandler>();
                                    this._playable.SetReferenceValue(TimelineAssetInfo.RefInfoID, rHandler);
                                }
                                rHandler.assetInfo = rAsset;
                                break;
                        }
                    }
                }
            }
            return rAsset.asset;
        }
    }

    public class StoryNpc : IReusableClass
    {
        public StoryNpcEntity entity;
        public GameObject gameObject;
        public Transform transform;
        public uint MaxStore => 5;
        public void OnReset()
        {
            if (this.entity != null)
            {
                this.entity.EntityGroup.HideEntity(this.entity);
                this.entity = null;
            }
            this.gameObject = null;
            this.transform = null;
        }
    }
    
    public class StoryNpcEntity : Entity
    {
        
    }
}